<?php
class File_Movie_Util
{
	/**
	 * 動画ファイルか判定する
	 *
	 * @param string $file_path
	 * @return bool
	 */
	public static function isMovieFile($filename)
	{
		if(!file_exists($filename)){
			return false;
		}

		$ffmpeg = @new ffmpeg_movie($filename);
		if(!$ffmpeg instanceof ffmpeg_movie){
			return false;
		}

		return $ffmpeg->hasVideo();
	}

	/**
	 * ファイルのハッシュ値を求める
	 * @param string $filedata
	 * @return string
	 */
	public static function hash($filedata)
	{
		return md5($filedata);
	}

	/**
	 * FLVにエンコードを行う
	 *
	 * @param string $binary
	 * @throws File_Movie_Exception
	 * @return ffmpeg_movie
	 */
	public function encodeFlv($binary)
	{
		$inputFile = tempnam(TMP_DIR, "input_");
		if (file_put_contents($inputFile, $binary) === false) {
			throw new File_Movie_Exception('テンポラリファイルの作成に失敗');
		}

		// 拡張子付けないとnoticeが出る
		$outputFile = TMP_DIR . 'output_' . md5(uniqid(rand(), true)) . '.flv';

		$unlinkTemp = function () use ($inputFile, $outputFile)
		{
			if (file_exists($inputFile))
				unlink($inputFile);
			if (file_exists($outputFile))
				unlink($outputFile);
		};

		try {
			$options = array(
				'temp_dir'       => TMP_DIR,
				'output_dir'     => TMP_DIR,
				// 出力ファイルのディレクトリ
				'output_file'    => $outputFile,
				//変換後の動画ファイル
				'overwrite_mode' => PHPVideoToolkit::OVERWRITE_EXISTING,
			);

			$result = VideoTo::FLV($inputFile, $options);
		}
		catch (Exception $e) {
			$unlinkTemp();
			throw new File_Movie_Exception($e->getMessage());
		}

		if (!$result) {
			$unlinkTemp();
			throw new File_Movie_Exception(VideoTo::getError(true)[0]);
		}

		return new ffmpeg_movie($outputFile);
	}

	/**
	 * FLVのエンコード
	 *
	 * @param int $movie_id
	 * @param bool optional $force_flg
	 * @return void
	 */
	public function encodeFlvMovie($movie_id, $force_flg=false)
	{
		$dbMovie = new Db_Table_TMovie();
		$row = $dbMovie->getForEncodeByMovieId($movie_id, $force_flg);

		if(!$row)return;

		$inputFile = tempnam(TMP_DIR, "input_");
		if(file_put_contents($inputFile, $row['filedata']) === false){
			$dbMovie->updateEncodeStatus($movie_id, C_MOVIE_STATUS_NG, 'テンポラリファイルの作成に失敗');
			return;
		}

		// 拡張子付けないとnoticeが出る
		$outputFile = TMP_DIR . 'output_' . md5(uniqid(rand(), true)) . '.flv';

		$unlinkTemp = function()use($inputFile, $outputFile){
			if(file_exists($inputFile))unlink($inputFile);
			if(file_exists($outputFile))unlink($outputFile);
		};

		try{
			$options = array(
				'temp_dir'    		=> TMP_DIR,
				'output_dir'  		=> TMP_DIR, // 出力ファイルのディレクトリ
				'output_file' 		=> $outputFile, //変換後の動画ファイル
				'overwrite_mode'	=> PHPVideoToolkit::OVERWRITE_EXISTING,
			);

			$result = VideoTo::FLV($inputFile, $options);
		}catch (Exception $e){
			$unlinkTemp();
			$dbMovie->updateEncodeStatus($movie_id, C_MOVIE_STATUS_NG, $e->getMessage());
			return;
		}

		if(!$result){
			$unlinkTemp();
			$dbMovie->updateEncodeStatus($movie_id, C_MOVIE_STATUS_NG, VideoTo::getError(true)[0]);
			return;
		}

		// フレーム数を計算(普通にやるとなんか全然あてにならない）
		$movie = new ffmpeg_movie($outputFile);
		$frameCount = 1;
		while(true){
			$frame = $movie->getFrame($frameCount);
			if(!$frame instanceof ffmpeg_frame){
				break;
			}
			$frameCount++;
		}
		$frameCount--;

		// サムネイルの作成
		$imgData = $this->getThumbnailData($outputFile, intval($frameCount/2), $frameCount);

		// サムネイルと動画の保存
		$movieData = file_get_contents($outputFile);
		$dbMovie->updateEncodeSuccess($movie_id, $movieData, $frameCount, $imgData);
		$unlinkTemp();
	}

	/**
	 * サムネイルを作成
	 *
	 * @param string $flvfileName
	 * @param int $target_frame
	 * @param int $maxFrameCount
	 * @throws AppException
	 * @return string
	 */
	public function getThumbnailData($flvfileName, $target_frame, $maxFrameCount)
	{
		$movie = new ffmpeg_movie($flvfileName);

		if (!$movie) {
			throw new AppException('ffmpeg_movieインスタンス作成失敗');
		}

		$movie_width = $movie->getFrameWidth();
		$movie_height = $movie->getFrameHeight();

		// 秒数の調節
		if($target_frame > $maxFrameCount){
			$target_frame = $maxFrameCount;
		}
		elseif($target_frame <= 0){
			$target_frame = 1;
		}

		$frame = $movie->getFrame($target_frame);
		// GD イメージオブジェクト生成
		$image = $frame->toGDImage();
		// 画像の幅と高さを取得
		$width = ImageSX($image);
		$height = ImageSY($image);
		// 縮小比率を計算
		$width_rate = C_THUMBNAIL_WIDTH / $width;
		$height_rate = C_THUMBNAIL_HEIGHT / $height;
		if ($height_rate < $width_rate) {
			$rate = $height_rate;
		} else {
			$rate = $width_rate;
		}
		$new_width = $width * $rate;
		$new_height = $height * $rate;

		// リサイズした画像オブジェクトを生成
		$new_img = ImageCreateTrueColor($new_width, $new_height);
		ImageCopyResized($new_img, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

		ob_start();
		ImageJPEG($new_img, null, 100);
		$ret = ob_get_contents();
		ob_end_clean();

		return $ret;
	}

	/**
	 * ファイルデータからサムネイル作成
	 *
	 * @param string $fileData
	 * @param int $target_frame
	 * @param int $maxFrameCount
	 * @throws AppException
	 * @return string
	 */
	public function getThumnailDataByFileData($fileData, $target_frame, $maxFrameCount)
	{
		$outputFile = TMP_DIR . 'output_' . md5(uniqid(rand(), true)) . '.flv';
		file_put_contents($outputFile, $fileData);

		try {
			$ret = $this->getThumbnailData($outputFile, $target_frame, $maxFrameCount);

			unlink($outputFile);

			return $ret;
		} catch (Exception $e) {
			unlink($outputFile);
			throw $e;
		}
	}
}